home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FishMarket 1.0
/
FishMarket v1.0.iso
/
fishies
/
351-375
/
disk_353
/
compdisk
/
compsub.c
< prev
next >
Wrap
Text File
|
1992-05-06
|
5KB
|
354 lines
long __regargs memwrite(char *,long);
void compexit(void);
long compinit(void);
long __regargs compfiles(unsigned char *,long,unsigned char *,long);
long compress(void);
void __regargs output(long);
void cl_block(void);
void cl_hash(long);
#define BITS 12
#if BITS == 16
# define HSIZE 69001
#endif
#if BITS == 15
# define HSIZE 35023
#endif
#if BITS == 14
# define HSIZE 18013
#endif
#if BITS == 13
# define HSIZE 9001
#endif
#if BITS <= 12
# define HSIZE 5003
#endif
#define BLOCK_MASK 0x80
#define INIT_BITS 9
#define htabof(i) htab[i]
#define codetabof(i) codetab[i]
#define MAXCODE(n_bits) ((1 << (n_bits)) - 1)
#define CHECK_GAP 10000
#define FIRST 257
#define CLEAR 256
#define myfgetc() (reallyread++ >= watermark) ? EOF : *sect++
#define absmin(a,b) ((a > b) ? b : a)
long n_bits,maxcode,*htab,hsize,free_ent,clear_flg,ratio,checkpoint,offset,in_count,bytes_out,reallywritten,watermark,buffsize,reallyread;
unsigned char *buffstart,*sect;
unsigned short *codetab;
char buf[BITS];
const unsigned char lmask[9] = {0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x00};
const unsigned char rmask[9] = {0x00,0x01,0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF};
long __regargs
memwrite(mem,size)
register char *mem;
register long size;
{
register long byteswritten = 0;
while(size-- > 0)
{
if(reallywritten++ < buffsize)
{
*buffstart++ = *mem++;
byteswritten++;
}
else
return(byteswritten);
}
return(byteswritten);
}
void
compexit()
{
if(htab)
FreeMem(htab,HSIZE * sizeof(long));
if(codetab)
FreeMem(codetab,HSIZE * sizeof(unsigned short));
htab = NULL;
codetab = NULL;
}
long
compinit()
{
if(!(htab = (long *)AllocMem(HSIZE * sizeof(long),0)))
return(FALSE);
if(!(codetab = (unsigned short *)AllocMem(HSIZE * sizeof(unsigned short),0)))
{
FreeMem(htab,HSIZE * sizeof(long));
htab = NULL;
return(FALSE);
}
return(TRUE);
}
void __regargs
output(code)
long code;
{
long r_off = offset, bits = n_bits;
register char *bp = buf;
if(code >= 0)
{
bp += (r_off >> 3);
r_off &= 7;
*bp = (*bp & rmask[r_off]) | (code << r_off) & lmask[r_off];
bp++;
bits -= (8 - r_off);
code >>= 8 - r_off;
if(bits >= 8)
{
*bp++ = code;
code >>= 8;
bits -= 8;
}
if(bits)
*bp = code;
offset += n_bits;
if(offset == (n_bits << 3))
{
bp = buf;
bits = n_bits;
bytes_out += bits;
do
{
if(reallywritten++ < buffsize)
*buffstart++ = *bp++;
}
while(--bits);
offset = 0;
}
if(free_ent > maxcode || (clear_flg > 0))
{
if(offset > 0)
{
memwrite(buf,n_bits);
bytes_out += n_bits;
}
offset = 0;
if(clear_flg)
{
maxcode = MAXCODE(n_bits = INIT_BITS);
clear_flg = 0;
}
else
{
n_bits++;
if(n_bits == BITS)
maxcode = (1 << BITS);
else
maxcode = MAXCODE(n_bits);
}
}
}
else
{
if(offset > 0)
memwrite(buf,(offset + 7) / 8);
bytes_out += (offset + 7) / 8;
offset = 0;
}
}
void
cl_block()
{
register long rat;
checkpoint = in_count + CHECK_GAP;
if(in_count > 0x007FFFFF)
{
rat = bytes_out >> 8;
if(rat == 0)
rat = 0x7FFFFFFF;
else
rat = in_count /rat;
}
else
rat = (in_count << 8) / bytes_out;
if(rat > ratio)
ratio = rat;
else
{
ratio = 0;
cl_hash((long)hsize);
free_ent = FIRST;
clear_flg = 1;
output((long)CLEAR);
}
}
void
cl_hash(hashsize)
long hashsize;
{
register long *htab_p = &htab[hashsize],i;
register unsigned short j;
i = hashsize - 16;
do
{
for(j = 16 ; j > 0 ; j--)
*(htab_p - j) = -1;
htab_p -= 16;
}
while((i -= 16) >= 0);
for(i += 16 ; i > 0 ; i--)
*--htab_p = -1;
}
long __regargs
compfiles(from,sectsize,to,maxsize)
unsigned char *from,*to;
long sectsize,maxsize;
{
sect = from;
watermark = sectsize;
buffstart = to;
buffsize = maxsize;
reallywritten = 0;
reallyread = 0;
hsize = HSIZE;
free_ent = 0;
clear_flg = 0;
ratio = 0;
checkpoint = CHECK_GAP;
in_count = 1;
if(sectsize < (1 << 12))
hsize = absmin(5003, HSIZE);
else if(sectsize < (1 << 13))
hsize = absmin(9001, HSIZE);
else if(sectsize < (1 << 14))
hsize = absmin(18013, HSIZE);
else if(sectsize < (1 << 15))
hsize = absmin(35023, HSIZE);
else if(sectsize < 47000)
hsize = absmin(50021, HSIZE);
compress();
return(reallywritten);
}
long
compress()
{
long fcode,i = 0,c,ent,disp,hsize_reg,hshift = 0;
offset = 0;
bytes_out = 3;
clear_flg = 0;
ratio = 0;
in_count = 1;
checkpoint = CHECK_GAP;
maxcode = MAXCODE(n_bits = INIT_BITS);
free_ent = ((BLOCK_MASK) ? FIRST : 256);
ent = myfgetc();
for(fcode = (long)hsize ; fcode < 65536L ; fcode *= 2L)
hshift++;
hshift = 8 - hshift;
hsize_reg = hsize;
cl_hash((long)hsize_reg);
while((c = myfgetc()) != EOF)
{
in_count++;
fcode = (long)(((long) c << BITS) + ent);
i = ((c << hshift) ^ ent);
if(htabof(i) == fcode)
{
ent = codetabof(i);
continue;
}
else
if((long)htabof(i) < 0)
goto nomatch;
disp = hsize_reg - i;
if(i == 0)
disp = 1;
probe: if((i -= disp) < 0)
i += hsize_reg;
if(htabof(i) == fcode)
{
ent = codetabof(i);
continue;
}
if((long)htabof(i) > 0)
goto probe;
nomatch: output((long)ent);
ent = c;
if(free_ent < (1 << BITS))
{
codetabof(i) = free_ent++;
htabof(i) = fcode;
}
else
if((long)in_count >= checkpoint && BLOCK_MASK)
cl_block();
}
output((long)ent);
output((long)-1);
return(bytes_out);
}